home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / sozobon2.zoo / top / npeep2.c < prev    next >
C/C++ Source or Header  |  1990-12-14  |  18KB  |  856 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. /*
  13.  * 2-instruction peephole optimizations
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18. /*
  19.  * Macros to reference commonly-used values... cleans up the following
  20.  * code quite a bit.
  21.  */
  22. #define    sm1    i1->src.amode    /* source & dest addressing modes */
  23. #define    dm1    i1->dst.amode
  24. #define    sm2    i2->src.amode
  25. #define    dm2    i2->dst.amode
  26.  
  27. #define    sr1    i1->src.areg    /* source & dest registers */
  28. #define    dr1    i1->dst.areg
  29. #define    sr2    i2->src.areg
  30. #define    dr2    i2->dst.areg
  31.  
  32.  
  33. /*
  34.  * ipeep2(bp, i1) - look for 2-instruction optimizations at the given inst.
  35.  */
  36. static    int
  37. ipeep2(bp, i1)
  38. BLOCK    *bp;
  39. register INST    *i1;
  40. {
  41.     register INST    *i2;        /* the next instruction */
  42.     register INST    *ti2;        /* "temporary" next inst */
  43.  
  44.     register int    op1, op2;    /* opcodes, for speed */
  45.  
  46.     i2  = i1->next;
  47.     op1 = i1->opcode;
  48.     op2 = i2->opcode;
  49.  
  50.     /*
  51.      * Avoid stack fix-ups after a call if possible.
  52.      */
  53.  
  54.     /*
  55.      *    addq    #4,sp
  56.      *    ... stuff that doesn't use SP ...
  57.      *    move.l    ?,-(sp)        =>    move.l    ?,(sp)
  58.      */
  59.     if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 4 &&
  60.         dm1 == REG && dr1 == SP) {
  61.  
  62.         ti2 = i2;
  63.         while (!uses(ti2, SP)) {
  64.             if (ti2->next == NULL)
  65.                 goto end2;
  66.             ti2 = ti2->next;
  67.         }
  68.  
  69.         if (ti2->opcode == MOVE && ti2->flags == LENL &&
  70.             ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
  71.                 ti2->dst.amode = REGI;
  72.                 delinst(bp, i1);
  73.                 DBG(printf("%d ", __LINE__))
  74.                 return CLEAN;
  75.         }
  76.     }
  77. end2:
  78.  
  79.     /*
  80.      *    addq    #2,sp
  81.      *    ... stuff that doesn't use SP ...
  82.      *    move.w    ?,-(sp)        =>    move.w    ?,(sp)
  83.      */
  84.     if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 2 &&
  85.         dm1 == REG && dr1 == SP) {
  86.  
  87.         ti2 = i2;
  88.         while (!uses(ti2, SP)) {
  89.             if (ti2->next == NULL)
  90.                 goto end3;
  91.             ti2 = ti2->next;
  92.         }
  93.  
  94.         if (ti2->opcode == MOVE && ti2->flags == LENW &&
  95.             ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
  96.                 ti2->dst.amode = REGI;
  97.                 delinst(bp, i1);
  98.                 DBG(printf("%d ", __LINE__))
  99.                 return CLEAN;
  100.         }
  101.     }
  102. end3:
  103.  
  104.     /*
  105.      * Avoid "tst" instructions following instructions that
  106.      * set the Z flag.
  107.      */
  108.  
  109.     /*
  110.      *    move.x    X, Y        =>    move.x    X, Y
  111.      *    tst.x    X or Y            ...deleted...
  112.      *    beq/bne                beq/bne
  113.      *
  114.      *    Where Y is not An, because "movea" doesn't set the
  115.      *    zero flag.
  116.      */
  117.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  118.         op1 == MOVE && op2 == TST &&
  119.         i1->flags == i2->flags) {
  120.  
  121.         /*
  122.          * If pre-decrement is set on the dest. of the move,
  123.          * don't let that screw up the operand comparison.
  124.          */
  125.         if (dm1 & DEC)
  126.             dm1 &= ~DEC;
  127.  
  128.         if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
  129.             if (dm1 != REG || ISD(dr1)) {
  130.                     delinst(bp, i2);
  131.                     DBG(printf("%d ", __LINE__))
  132.                     return CLEAN;
  133.             }
  134.         }
  135.     }
  136.  
  137.     /*
  138.      *    and.x    X, Y        =>    and.x    X, Y
  139.      *    tst.x    X or Y            ...deleted...
  140.      *    beq/bne                beq/bne
  141.      *
  142.      *    Where Y is not An, because "movea" doesn't set the
  143.      *    zero flag.
  144.      */
  145.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  146.         op1 == AND && op2 == TST &&
  147.         i1->flags == i2->flags) {
  148.  
  149.         /*
  150.          * If pre-decrement is set on the dest. of the move,
  151.          * don't let that screw up the operand comparison.
  152.          */
  153.         if (dm1 & DEC)
  154.             dm1 &= ~DEC;
  155.  
  156.         if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
  157.             if (dm1 != REG || ISD(dr1)) {
  158.                     delinst(bp, i2);
  159.                     DBG(printf("%d ", __LINE__))
  160.                     return CLEAN;
  161.             }
  162.         }
  163.     }
  164.  
  165.     /*
  166.      *    ext.x    Dn        =>    ext.x    Dn
  167.      *    tst.x    Dn            ...deleted...
  168.      *    beq/bne                beq/bne
  169.      *
  170.      *    Where Y is not An, because "movea" doesn't set the
  171.      *    zero flag.
  172.      */
  173.     if ((bp->last == i2) && (bp->bcode == BEQ || bp->bcode == BNE) &&
  174.         (op1 == EXT) && (op2 == TST) &&
  175.         (i1->flags == i2->flags)) {
  176.  
  177.         if ((sm1 == REG) && ISD(sr1) && (sm2 == REG) && (sr1 == sr2)) {
  178.                 delinst(bp, i2);
  179.                 DBG(printf("%d ", __LINE__))
  180.                 return CLEAN;
  181.         }
  182.     }
  183.  
  184.     /*
  185.      *    move.?    X, Dn        =>    move.?    X, Dn
  186.      *    ext.?    Dn            ...deleted...
  187.      *    beq/bne                beq/bne
  188.      *
  189.      *    Where Dn is dead after the "ext".
  190.      */
  191.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  192.         op1 == MOVE && op2 == EXT) {
  193.  
  194.         if ((dm1 == REG) && ISD(dr1) &&
  195.             (sm2 == REG) && (dr1 == sr2)) {
  196.             if ((i2->live & RM(sr2)) == 0) {
  197.                 delinst(bp, i2);
  198.                     DBG(printf("%d ", __LINE__))
  199.                  return CLEAN;
  200.             }
  201.         }
  202.     }
  203.  
  204.     /*
  205.      *    ext.l    Dm        =>    ...deleted...
  206.      *    tst.l    Dm            tst.w    Dm
  207.      *
  208.      *    where Dm is dead after the "tst".
  209.      */
  210.     if (op1 == EXT && op2 == TST &&
  211.         ((i1->flags & LENL) != 0) &&  ((i2->flags & LENL) != 0) &&
  212.         (sr1 == sr2) && ISD(sr1)) {
  213.  
  214.         if ((i2->live & RM(sr2)) == 0) {
  215.             i2->flags = LENW;
  216.             delinst(bp, i1);
  217.                 DBG(printf("%d ", __LINE__))
  218.             return CLEAN;
  219.         }
  220.     }
  221.  
  222. #if 0
  223.     /*
  224.      *    add[q]    #?,sp
  225.      *    ... stuff that doesn't use SP ...
  226.      *    unlk    An        =>    unlk    An
  227.      */
  228.     if ((op1 == ADDQ || op1 == ADD) && sm1 == IMM &&
  229.          dm1 == REG && dr1 == SP) {
  230.  
  231.         ti2 = i2;
  232.         while (!uses(ti2, SP)) {
  233.             if (ti2->next == NULL)
  234.                 goto end8;
  235.             ti2 = ti2->next;
  236.         }
  237.         if (ti2->opcode == UNLK) {
  238.                  delinst(bp, i1);
  239.                 DBG(printf("%d ", __LINE__))
  240.                  return CLEAN;
  241.         }
  242.     }
  243. end8:
  244. #endif
  245.  
  246.     /*
  247.      *    ext.l    Dm        =>    ...deleted...
  248.      *    ???    N(An,Dm.l), ??        ???    N(An,Dm.w), ??
  249.      *
  250.      *    Where Dm is dead
  251.      */
  252.     if ((op1 == EXT) && (i1->flags & LENL) &&
  253.         (sm2 == (REGIDX|XLONG)) &&
  254.         (sr1 == i2->src.ireg)) {
  255.  
  256.         if ((i2->live & RM(sr1)) == 0) {
  257.             sm2 &= ~XLONG;
  258.             delinst(bp, i1);
  259.                 DBG(printf("%d ", __LINE__))
  260.             return CLEAN;
  261.         }
  262.     }
  263.  
  264.     /*
  265.      *    ext.l    Dm        =>    ...deleted...
  266.      *    ???    ??, N(An,Dm.l)        ???    ??, N(An,Dm.w)
  267.      *
  268.      *    Where Dm is dead
  269.      */
  270.     if ((op1 == EXT) && (i1->flags & LENL) &&
  271.         (dm2 == (REGIDX|XLONG)) &&
  272.         (sr1 == i2->dst.ireg)) {
  273.  
  274.         if ((i2->live & RM(sr1)) == 0) {
  275.             dm2  &= ~XLONG;
  276.             delinst(bp, i1);
  277.                 DBG(printf("%d ", __LINE__))
  278.             return CLEAN;
  279.         }
  280.     }
  281.  
  282.     /*
  283.      * Avoid intermediate registers.
  284.      */
  285.  
  286.     /*
  287.      *    move.x    X, Dm        =>    INST.x    X, Dn
  288.      *    INST.x    Dm, Dn
  289.      *
  290.      *    where Dm is dead, and INST is one of: add, sub, and, or, cmp
  291.      */
  292.     if ((op1 == MOVE) &&
  293.         ((op2==ADD)||(op2==SUB)||(op2==AND)||(op2==OR)||(op2==CMP)) &&
  294.         (i1->flags == i2->flags) &&
  295.         (dm1 == REG) && ISD(dr1) &&
  296.         (sm2 == REG) && ISD(sr2) &&
  297.         (dm2 == REG) && ISD(dr2) &&
  298.         (dr1 == sr2)) {
  299.  
  300.         if ((i2->live & RM(sr2)) == 0) {
  301.  
  302.             i1->opcode = i2->opcode;
  303.             dr1 = dr2;
  304.  
  305.             delinst(bp, i2);
  306.                 DBG(printf("%d ", __LINE__))
  307.             return DIRTY;
  308.         }
  309.     }
  310.  
  311.     /*
  312.      * Silly moves
  313.      */
  314.  
  315.     /*
  316.      *    move.x    X, Y        =>    move.x    X, Y
  317.      *    move.x    Y, X
  318.      */
  319.     if ((op1 == MOVE) && (op2 == MOVE) &&
  320.         (i1->flags == i2->flags) &&
  321.         opeq(&i1->src, &i2->dst) && opeq(&i1->dst, &i2->src) &&
  322.         ((sm1 & (INC|DEC)) == 0) &&
  323.         ((dm1 & (INC|DEC)) == 0)) {
  324.  
  325.              delinst(bp, i2);
  326.             DBG(printf("%d ", __LINE__))
  327.              return CLEAN;
  328.     }
  329.  
  330.     /*
  331.      *    move.x    X, Y        =>    move.x    X, Rn
  332.      *    move.x    Y, Rn            move.x    Rn, Y
  333.      *
  334.      *    where Y isn't INC or DEC, and isn't register direct
  335.      */
  336.     if ((op1 == MOVE) && (op2 == MOVE) && (dm2 == REG) &&
  337.         opeq(&i1->dst, &i2->src) && ((dm1 & (INC|DEC)) == 0) &&
  338.         (i1->flags == i2->flags) && (dm1 != REG)) {
  339.  
  340.         freeop(&i1->dst);
  341.         i1->dst = i2->dst;
  342.         i2->dst = i2->src;
  343.         i2->src = i1->dst;
  344.  
  345.             DBG(printf("%d ", __LINE__))
  346.         return CLEAN;
  347.     }
  348.  
  349.     /*
  350.      *    move.x    Dm, X        =>    move.x    Dm, X
  351.      *    move.x    X, Y            move.x    Dm, Y
  352.      *
  353.      * Where 'x' is the same, and 'X' has no side-effects.
  354.      */
  355.     if ((op1 == MOVE) && (op2 == MOVE) &&
  356.         (sm1 == REG) && ISD(sr1) &&
  357.         (i1->flags == i2->flags) && opeq(&i1->dst, &i2->src) &&
  358.         ((dm1 & (DEC|IN